package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.MnSAPStatus;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.IntegrateUtils;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.cz.base.tool.DateFormatUtil;
import com.alibaba.cz.base.tool.feature.Features;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.crunifiedinventory.api.invoiceorderwrite.service.InvoiceOrderWriteService;
import com.epoch.app.crunifiedinventory.domain.invoiceorder.dto.SearchRequest;
import com.epoch.app.crunifiedinventory.domain.invoiceorder.model.InvoiceOrder;
import com.epoch.app.crunifiedinventory.domain.invoiceorder.service.InvoiceOrderService;
import com.epoch.app.crunifiedinventory.domain.invoiceorderdetail.model.InvoiceOrderDetail;
import com.epoch.app.crunifiedinventory.domain.invoiceorderdetail.service.InvoiceOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.request.InvoiceOrderCreateRequest;
import com.epoch.app.crunifiedinventory.dto.request.InvoiceOrderDetailCreateDTO;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommDetail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommSDO;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf016Detail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf016Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf016SDO;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif016v2.service.MnSapIf016V2Service;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangguoqing
 * @date 2021/10/12
 * @Description sap请求平台同步发票016
 */
@Component
@Primary
public class MnSapIf016V2ServiceImpl implements MnSapIf016V2Service {
    private final Log log = Log.getLogger(MnSapIf016V2Service.class);

    @Autowired
    private InvoiceOrderWriteService invoiceOrderWriteService;
    @Resource
    private InvoiceOrderService invoiceOrderService;
    @Resource
    private InvoiceOrderDetailService invoiceOrderDetailService;
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private EpochCacheService epochCacheService;

    private static final String INVOICE_ORDER_CACHE_KEY = "INVOICE_ORDER_CACHE_KEY_";
    //设置sap过期时间为
    private static final Long SAP_TIMESTAMP_CACHE_EXPIRE = 60 * 60 * 24 * 100L;

    @Override
    @ProcessInvoker(remark = "MnSapIf016V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public MnSapCommResponse externalSyncInvoice(MnSapIf016Request mnSapIf016Request) {
        log.info("MnSapIf016V2ServiceImpl mnSapIf016Request={}",JSON.toJSONString(mnSapIf016Request));
        MnSapCommResponse mnSapCommResponse = new MnSapCommResponse();
        List<MnSapCommSDO> sapCommSDOList = Lists.newArrayList();
//        mnSapIf016Request.getData().forEach(x -> {
//            InvoiceOrderCreateRequest invoiceOrderCreateRequest = convertRequest2InvoiceOrderCreateRequest(x);
//            invoiceOrderWriteService.createInvoiceOrder(invoiceOrderCreateRequest);
//            sapCommSDOList.add(convert2SapCommSDO(x));
//        });

        // Try to get from mogodb if null
        if (mnSapIf016Request == null) {
            mnSapIf016Request = IntegrateUtils.safeGetMessageObject(MnSapIf016Request.class);
        }

        //如果库中有了 就不新增了
        try{
            for(MnSapIf016SDO mnSapIf016SDO :mnSapIf016Request.getData()){
                //如果需要检测时间戳
//                if ( checkTimestamp){
//                    String check = ResponseUtil.check(mnSapIf016SDO.getExt());
//                    if (StringUtils.isNotBlank(check)){
//                        saveSapRetry(mnSapIf016Request,check);
//                        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
//                        mnSapCommSDO.setStatus("E");
//                        mnSapCommSDO.setMessage(check);
//                        mnSapCommSDO.setHeaderKey(mnSapIf016SDO.getHeaderKey());
//                        List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
//                        mnSapCommSDOS.add(mnSapCommSDO);
//                        mnSapCommResponse.setData(mnSapCommSDOS);
//                        return mnSapCommResponse;
//                    }
//                    //判断是否需要时间戳
//                    if (!checkModifierTime(mnSapIf016SDO)){
//                        saveSapRetry(mnSapIf016Request,"当前修改时间早于上一次 不允许更新");
//                        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
//                        mnSapCommSDO.setStatus("E");
//                        mnSapCommSDO.setMessage("当前修改时间早于上一次 不允许更新");
//                        mnSapCommSDO.setHeaderKey(mnSapIf016SDO.getHeaderKey());
//                        List<MnSapCommSDO> mnSapCommSDOS = Lists.newArrayList();
//                        mnSapCommSDOS.add(mnSapCommSDO);
//                        mnSapCommResponse.setData(mnSapCommSDOS);
//                        return mnSapCommResponse;
//                    }else {
//                        cache(mnSapIf016Request.getData().get(0).getInvoiceId(),mnSapIf016Request.getData().get(0).getExt());
//                    }
//                }
                SearchRequest searchRequest = new SearchRequest();
                searchRequest.setInvoiceOrderId(mnSapIf016SDO.getInvoiceId());
                Result<List<InvoiceOrder>> search = invoiceOrderService.search(searchRequest);
                InvoiceOrderCreateRequest invoiceOrderCreateRequest = convertRequest2InvoiceOrderCreateRequest(mnSapIf016SDO);
                if (Objects.isNull(search)||CollectionUtils.isEmpty(search.getResult())){
                    invoiceOrderWriteService.createInvoiceOrder(invoiceOrderCreateRequest);
                }else {
                    //更新
                    invoiceOrderCreateRequest.setId(search.getResult().get(0).getId());
                    InvoiceOrderDetail invoiceOrderDetail = new InvoiceOrderDetail();
                    invoiceOrderDetail.setInvoiceOrdeId(search.getResult().get(0).getId());
                    Result<List<InvoiceOrderDetail>> invoiceOrderDetailsResult = invoiceOrderDetailService.search(invoiceOrderDetail);
                    List<Long> invoiceOrderDetailIds = new ArrayList<>();
                    if (!Objects.isNull(search) && !CollectionUtils.isEmpty(search.getResult())){
                        invoiceOrderDetailsResult.getResult().forEach(i -> {
                            invoiceOrderDetailIds.add(i.getId());
                        });
                    }
                    invoiceOrderCreateRequest.setInvoiceOrderDetailIds(invoiceOrderDetailIds);
                    invoiceOrderWriteService.updateInvoiceOrder(invoiceOrderCreateRequest);
                }
                sapCommSDOList.add(convert2SapCommSDO(mnSapIf016SDO));
            }

        }catch (Throwable e){
            log.error("MnSapIf016ServiceImpl_invoice_write_error",e);
//            saveSapRetry(mnSapIf016Request,e.getMessage());
        }
        mnSapCommResponse.setData(sapCommSDOList);
        mnSapCommResponse.setMessageId(mnSapIf016Request.getMessageHeader().getMessageId());
        mnSapCommResponse.setInterfacePath(mnSapIf016Request.getMessageHeader().getInterfacePath());
        return mnSapCommResponse;
    }

    private InvoiceOrderCreateRequest convertRequest2InvoiceOrderCreateRequest(MnSapIf016SDO mnSapIf016SDO) {
        InvoiceOrderCreateRequest invoiceOrderCreateRequest = new InvoiceOrderCreateRequest();

        invoiceOrderCreateRequest.setInvoiceOrderId(mnSapIf016SDO.getInvoiceId());
        invoiceOrderCreateRequest.setReverseInvoiceId(mnSapIf016SDO.getReverseInvoiceId());
        invoiceOrderCreateRequest.setCompanyCode(mnSapIf016SDO.getCompanyCode());
        if (CollectionUtils.isNotEmpty(mnSapIf016SDO.getItems())){
            MnSapIf016Detail mnSapIf016Detail = mnSapIf016SDO.getItems().get(0);
            invoiceOrderCreateRequest.setDeliveryOrderId(mnSapIf016Detail.getDeliveryOrderId());
            invoiceOrderCreateRequest.setSourceOrderId(mnSapIf016Detail.getSourceOrderId());
        }

        Features features = Features.newFeatures(mnSapIf016SDO.getFeatures());
        invoiceOrderCreateRequest.setFeature(features.getOriginMap());
        //日期格式：yyyyMMdd(20150825)
        try {
            invoiceOrderCreateRequest.setCreateDate(DateFormatUtil.parseStrToDate(mnSapIf016SDO.getCreateDate(),"yyyyMMdd"));
            invoiceOrderCreateRequest.setSapGenerateTime(DateFormatUtil.parseStrToDate(mnSapIf016SDO.getGenerateTime(),"yyyyMMdd"));
        }catch (Exception e){
                throw  new FacadeException("OTS-03-001-15-017");
        }

        invoiceOrderCreateRequest.setSaleOrganizationCode(mnSapIf016SDO.getSaleOrganizationCode());
        invoiceOrderCreateRequest.setType(mnSapIf016SDO.getType());

        List<InvoiceOrderDetailCreateDTO> detailCreateDTOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(mnSapIf016SDO.getItems())) {
            mnSapIf016SDO.getItems().forEach(item -> {
                detailCreateDTOList.add(convert2InvoiceOrderDetailCreateDTO(item));
            });
        }
        invoiceOrderCreateRequest.setCreator(mnSapIf016SDO.getCreator());
        invoiceOrderCreateRequest.setDetailList(detailCreateDTOList);
        return invoiceOrderCreateRequest;
    }

    private MnSapCommSDO convert2SapCommSDO(MnSapIf016SDO mnSapIf016SDO) {
        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
        mnSapCommSDO.setHeaderKey(mnSapIf016SDO.getHeaderKey());
        mnSapCommSDO.setStatus(MnSAPStatus.SUCCESS.getCode());

        List<MnSapCommDetail> detailList = Lists.newArrayList();
        mnSapIf016SDO.getItems().forEach(item -> {
            MnSapCommDetail detail = new MnSapCommDetail();
            detail.setStatus(MnSAPStatus.SUCCESS.getCode());
            detail.setItemKey(item.getItem_key());
            detailList.add(detail);
        });

        mnSapCommSDO.setItem(detailList);
        return mnSapCommSDO;
    }

    private InvoiceOrderDetailCreateDTO convert2InvoiceOrderDetailCreateDTO(MnSapIf016Detail item) {
        InvoiceOrderDetailCreateDTO createDTO = new InvoiceOrderDetailCreateDTO();
        //物料编号/货品编码
        if (Objects.nonNull(item.getScItemId())) {
            String s = item.getScItemId();
            if (s.length()>12){
                s = s.substring(s.length()-12);
            }
            createDTO.setScItemId(s);
        }
        createDTO.setTitle(item.getTitle());
        //价格转换 sap传来是元，这里转成分
        createDTO.setPrice(SapAndCrmFieldDealUtils.toLongByPrice(item.getPrice()));
        if (StringUtils.isNotBlank(item.getQuantity())) {
            BigDecimal quantity = new BigDecimal(item.getQuantity().trim());
            createDTO.setQuantity(quantity.stripTrailingZeros().toPlainString());
        }
        //折扣后总金额
        createDTO.setSubTotalAmount(SapAndCrmFieldDealUtils.toLongByPrice(item.getSubTotalAmount()));
        createDTO.setFeature(SapAndCrmFieldDealUtils.String2FeatureMap(item.getFeatures()));
        createDTO.setOrderLineId(item.getOrderLineId());
        createDTO.setDeliveryOrderLineId(item.getDeliveryOrderLineId());
        createDTO.setSalesOrderLineId(item.getSalesOrderLineId());
        createDTO.setDeliveryOrderId(item.getDeliveryOrderId());
        createDTO.setSourceOrderId(item.getSourceOrderId());
        return createDTO;
    }
    public void saveSapRetry(MnSapIf016Request request,String message){
        try {
            if (request == null){
                return;
            }
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(message);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            //请求时间戳
            MnSapIf016SDO sdo = request.getData().get(0);
//            sapRetrySaveRequest.setRequestTime();
            sapRetrySaveRequest.setOutKey(sdo.getInvoiceId());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP016.getValue());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        }catch (Throwable e){
            log.error("sapRetrySaveError",e);
        }
    }
    boolean checkModifierTime(MnSapIf016SDO sdo){
        String modifierTime = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),
                INVOICE_ORDER_CACHE_KEY + sdo.getInvoiceId());
        String ext = sdo.getExt();
        if (StringUtils.isNotBlank(modifierTime)){
            String[] modifierTimeArray = modifierTime.split("\\.");
            String[] extArray = ext.split("\\.");
            if (Long.parseLong(modifierTimeArray[0]) > Long.parseLong(extArray[0])) {
                return false;
            } else if (Long.valueOf(modifierTimeArray[0]).longValue() == Long.valueOf(extArray[0]).longValue()) {
                if (Long.parseLong(modifierTimeArray[1]) >= Integer.valueOf(extArray[1]).longValue()) {
                    return false;
                }
            }
        }
        return true;
    }
    void cache(String key,String time){
        if (StringUtils.isAnyBlank(key,time)){
            return;
        }
        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(),
                INVOICE_ORDER_CACHE_KEY + key,time,
                SAP_TIMESTAMP_CACHE_EXPIRE,
                TimeUnit.SECONDS);
    }
}
